package main

import (
	. "fmt"
	"reflect"
)

//动态获取变量的各种信息，如类型type，类别kind
//如果是结构体变量，还可以获取字段，方法等信息
//通过反射可以修改变量的值，可以调用关联的方法

//reflect.TypeOf(变量名)  获取变量的类型。返回reflect.Type类型
//reflect.ValueOf(变量名)  获取变量的值，返回reflect.Value类型（一个结构体类型）。
//	通过reflect.Value可以获取关于变量的很多信息
//变量、interface{} 和 reflect.Value 是可以相互转换的
// 如下
func test(b interface{}) {
	rType := reflect.TypeOf(b)
	//rType为类型, rType.Kind()为类别。二者可能值相同，也可能不同
	Println("rType:", rType, rType.Kind(), rType.Name(), rType.Size())

	// 将interface{}转为 reflect.Value
	rVal := reflect.ValueOf(b)
	Printf("rVal:类型--%T,类别--%v，值--%v\n", rVal, rVal.Kind(), rVal)

	// 修改变量的值
	// 注此方法需要函数传参以指针方式传地址
	//通过指针传递参数时，rVal.Kind()获取的时ptr类型，并不是Int64,因此需要使用rVal.Elem().Kind() 获取Int64类型
	//rVal.Elem().SetInt(60)  //传递指针参数
	//Println(rVal)

	// 此时rVal并不能和int类型的数据进行运算
	// 使用反射后的方法
	n := 50 + rVal.Int()
	Println("n: ", n)

	// 将reflect.Value 转为interface{}
	iVal := rVal.Interface()
	Printf("%v---%T\n",iVal,iVal)

	// 将interface{}转为原变量。类型断言
	v := iVal.(int)
	Printf("v是:%v  %T\n",v,v)
	//Println(v+10)
}
func main() {
	num := 50
	test(num)
	//test(&num)
}
